package negocio.bd;

import base.Cliente;
import base.Direccion;
import base.Telefono;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import utiles.ConexionBD;
import utiles.Logger;


/**
 * Clase para el manejo de los datos relativos a los clientes en la base de datos.
 * @author Efren
 * @version 0.0.1
 /* @since 14/02/2013 
 */
public class BDClientes{
    public static String nombre = "nombre";
    public static String DNI = "dni";
    public static String primerApellido = "apellido1";
    public static String segundoApellido = "apellido2";
    public static String direccion = "idDireccion";
    public static String email = "email";
    public static String numero = "numeroTelefono";
    public static String descripcion = "descripcion";
    public static String idDireccion = "idDireccion";
    public static String tipoVia = "tipoVia";
    public static String nombreDireccion = "nombreDireccion";
    public static String numeroDireccion = "numero";
    public static String escalera = "escalera";
    public static String piso = "piso";
    public static String letra = "letra";
    public static String codigoPostal = "cp";
    public static String municipio = "municipio";
    
    /**
     * Método que añade una nueva dirección a la base de datos.
     * @param direccion Dirección a añadir
     * @return verdadero si se ha añadido correctamente y falso en caso contrario.
     */
    public static boolean añadirDireccion(Direccion direccion, String dni){
        if (!existeDireccion(direccion)){
            java.sql.Connection db = new ConexionBD().getConnection();
            try {
                java.sql.PreparedStatement insert = db.prepareStatement("INSERT INTO `gestionTienda`.`Direcciones` VALUES (?,?,?,?,?,?,?,?,?)");
                insert.setString(1, dni);
                insert.setString(2, direccion.getTipoVia());
                insert.setString(3, direccion.getNombreDireccion());
                insert.setInt(4, direccion.getNumero());
                insert.setString(5, direccion.getEscalera());
                insert.setInt(6, direccion.getPiso());
                insert.setString(7, direccion.getLetra());
                insert.setString(8, direccion.getCodigoPostal());
                insert.setString(9, direccion.getMunicipio());
                insert.executeUpdate();
                return true;
            } catch(SQLException ex){
                System.out.println(ex.getMessage());
            }
        }return false;
    }
    /**
     * Método que añade un nuevo cliente a la base de datos. 
     * @param cliente Cliente a añadir
     * @return verdadero si se ha añadido correctamente y falso si se ha producido un error o el cliente ya existía. 
     */
    public static boolean añadirCliente(Cliente cliente){
        java.sql.Connection db = new ConexionBD().getConnection();
        try {
            java.sql.PreparedStatement insert = db.prepareStatement("INSERT INTO `gestionTienda`.`Clientes` VALUES (?,?,?,?,?)");
            insert.setString(1, cliente.getDni());
            insert.setString(2, cliente.getNombre());
            if (cliente.getPrimerApellido() == null){
                insert.setString(3, "");
            }else {
                insert.setString(3, cliente.getPrimerApellido());
            }
            if (cliente.getSegundoApellido()== null){
                insert.setString(4, "");
            }else {
                insert.setString(4, cliente.getSegundoApellido());
            }

            if (cliente.getEmail() == null){
                insert.setString(5, "");
            }else {
                insert.setString(5, cliente.getEmail());
            }
            insert.executeUpdate();
            return true;
        } catch (SQLException ex){
            Logger.printError(ex.getMessage());
        }return false;
    }
    /**
     * Método que comprueba la existencia de una dirección determinada en la base de datos.
     * @param direccion Objeto a añadir
     * @return verdadero en caso de que exista la dirección o falso en caso contrario. 
     */
    public static boolean existeDireccion(Direccion direccion){
        //Mejorar eficiencia.
        java.sql.Connection db = new ConexionBD().getConnection();
        try {
            Statement select = db.createStatement();
            ResultSet res = select.executeQuery("SELECT * FROM `gestionTienda`.`Direcciones` WHERE idDireccion = '" + direccion.getIdDireccion() + "'");
            if (res.next()){
                return true;
            }
            select.close();
            res.close();
        } catch (SQLException ex){
            Logger.printError(ex.getMessage());
        }
        return false;
    }
    /**
     * Método que comprueba la existencia de un cliente en la base de datos.
     * @param dni el dni del cliente a buscar
     * @return verdadero si el cliente existe y falso en caso contrario.
     */
    public static boolean existeCliente(String dni){
        java.sql.Connection db = new ConexionBD().getConnection();
        try {
            Statement select = db.createStatement();
            ResultSet res = select.executeQuery("SELECT * FROM `gestionTienda`.`Clientes` WHERE " + DNI + " = '" + dni + "'");
            if (res.next()){
                return true;
            }
            select.close();
            res.close();
        } catch (SQLException ex){
            Logger.printError(ex.getMessage());
        }
        return false;
    }
    /**
     * Método que determina si las propiedades de un cliente han cambiado respecto a las almacenadas en la base de datos.
     * @param ncliente Cliente a comprobar
     * @return verdadero si ha cambiado y falso en caso contrario.
     */
    public static boolean cambiado(Cliente ncliente){
        java.sql.Connection db = new ConexionBD().getConnection();
        Cliente cliente;
        try {
            Statement select = db.createStatement();
            ResultSet res = select.executeQuery("SELECT * FROM `gestionTienda`.`Clientes` WHERE " + DNI + " = " + ncliente.getDni());
            if (res.next()){
                cliente = new Cliente();
                cliente.setDni(res.getString(DNI));
                cliente.setNombre(res.getString(nombre));
                cliente.setPrimerApellido(res.getString(primerApellido));
                cliente.setSegundoApellido(res.getString(segundoApellido));
                cliente.setDireccion(obtenerDireccion(cliente.getDni()));
                cliente.setEmail(res.getString(email));
                cliente.setTelefonos(obtenerTelefonosCliente(cliente.getDni()));
                return !cliente.equals(ncliente);
            }
        } catch (SQLException ex){
            Logger.printError(ex.getMessage());
        }return false;
    }
    public static boolean añadirTelefono(Telefono t, String dni){
        if (t.getNumero() != null){
            java.sql.Connection db = new ConexionBD().getConnection();
        try {
            java.sql.PreparedStatement insert = db.prepareStatement("INSERT INTO `gestionTienda`.`Telefonos` (`dni`, `numeroTelefono`,`descripcion`) VALUES (?,?,?)");
            insert.setString(1, dni);
            insert.setString(2, t.getNumero());
            if (t.getDescripcion()== null){
                insert.setString(3, "");
            } else {
                insert.setString(3, t.getDescripcion());
            }
            insert.executeUpdate();
            return true;
        } catch(SQLException ex){
            System.out.println(ex.getMessage());
        }
        }return false;
    }
    /**
     * Método que obtiene un cliente en base a una consulta a la base de datos.
     * @param dni Identificador del cliente a obtener
     * @return Un objeto de tipo cliente o null si el cliente no existe o se produce algún error.
     */
    public static Cliente obtenerCliente(String dni){
        java.sql.Connection db = new ConexionBD().getConnection();
        try {
            Statement select = db.createStatement();
            ResultSet res = select.executeQuery("SELECT * FROM `gestionTienda`.`Clientes` WHERE " + DNI + " = '" + dni + "'");
            if (res.next()){
                Cliente cliente = new Cliente();
                cliente.setDni(dni);
                cliente.setNombre(res.getString(nombre));
                cliente.setPrimerApellido(res.getString(primerApellido));
                cliente.setSegundoApellido(res.getString(segundoApellido));
                cliente.setDireccion(obtenerDireccion(cliente.getDni()));
                cliente.setEmail(res.getString(email));
                cliente.setTelefonos(obtenerTelefonosCliente(cliente.getDni()));
                return cliente;
            }
            select.close();
            res.close();
        } catch (SQLException ex){
            Logger.printError(ex.getMessage());
        }
        return null;
    }
    /**
     * Método para obtener una dirección basado en una busqueda de su id en la base de datos.
     * @param idDireccion entero con el id a buscar
     * @return Un objeto de tipo Direccion o null si se ha producido un error o la dirección no existe,
     * @see Direccion
     */
    public static Direccion obtenerDireccion(String idDireccion){
        java.sql.Connection db = new ConexionBD().getConnection();
        try {
            java.sql.Statement select = db.createStatement();
            java.sql.ResultSet res = select.executeQuery("SELECT * FROM `gestionTienda`.`Direcciones` WHERE " + BDClientes.idDireccion + " = '" + idDireccion+"'");
            if (res.next()){
                Direccion temp = new Direccion();
                temp.setIdDireccion(idDireccion);
                temp.setTipoVia(res.getString(tipoVia));
                temp.setNombreDireccion(res.getString(nombreDireccion));
                temp.setNumero(res.getInt(numeroDireccion));
                temp.setEscalera(res.getString(escalera));
                temp.setPiso(res.getInt(piso));
                temp.setLetra(res.getString(letra));
                temp.setCodigoPostal(res.getString(codigoPostal));
                temp.setMunicipio(res.getString(municipio));
                return temp;
            }
        } catch (SQLException ex){
            Logger.printError(ex.getMessage());
        }return null;
    }
    /**
     * Método que obtiene todas las direcciones almacenadas en la base de datos.
     * @return Un array de tipo Direccion o null si no existen direcciones almacenadas o se ha producido un error.
     */
    public static Direccion[] obtenerDirecciones(){
        java.sql.Connection db = new ConexionBD().getConnection();
        ArrayList<Direccion> direcciones = new ArrayList<>(0);
        try {
            java.sql.Statement select = db.createStatement();
            ResultSet res = select.executeQuery("SELECT * FROM `gestionTienda`.`Direcciones`");
            while (res.next()){
                Direccion temp = new Direccion();
                temp.setIdDireccion(res.getString(idDireccion));
                temp.setTipoVia(res.getString(tipoVia));
                temp.setNombreDireccion(res.getString(nombreDireccion));
                temp.setNumero(res.getInt(numeroDireccion));
                temp.setEscalera(res.getString(escalera));
                temp.setPiso(res.getInt(piso));
                temp.setLetra(res.getString(letra));
                temp.setCodigoPostal(res.getString(codigoPostal));
                temp.setMunicipio(res.getString(municipio));
                direcciones.add(temp);
            }
            return direcciones.toArray(new Direccion[0]);
        } catch (SQLException ex){
            Logger.printError(ex.getMessage());
        }
        return null;
    }
    public static Cliente[] obtenerClientes(){
        java.sql.Connection db = new ConexionBD().getConnection();
        ArrayList<Cliente> clientes = new ArrayList<>(0);
        try {
            Statement select = db.createStatement();
            ResultSet res = select.executeQuery("SELECT * FROM `gestionTienda`.`Clientes`");
            while (res.next()){
                Cliente cliente = new Cliente();
                cliente.setDni(res.getString(DNI));
                cliente.setNombre(res.getString(nombre));
                cliente.setPrimerApellido(res.getString(primerApellido));
                cliente.setSegundoApellido(res.getString(segundoApellido));
                cliente.setDireccion(obtenerDireccion(cliente.getDni()));
                cliente.setEmail(res.getString(email));
                cliente.setTelefonos(obtenerTelefonosCliente(cliente.getDni()));
                clientes.add(cliente);
            }
            return clientes.toArray(new Cliente[0]);
        } catch (SQLException ex){
            Logger.printError(ex.getMessage());
        }return null;
    }
    public static Telefono[] obtenerTelefonosCliente(String dni){
        java.sql.Connection db = new ConexionBD().getConnection();
        ArrayList<Telefono> ltelefonos = new ArrayList<>(0);
        try {
            //Creación y ejecución de la consulta.
            java.sql.Statement select = db.createStatement();
            ResultSet res = select.executeQuery("SELECT * FROM `gestionTienda`.`Telefonos` WHERE " + DNI + " = '" + dni+"'");
            //Recorrido de resultados y añadido a arraylist
            while (res.next()){
                Telefono temp = new Telefono();
                temp.setNumero(res.getString(numero));
                temp.setDescripcion(res.getString(descripcion));
                ltelefonos.add(temp);
            }
            //Devolución del resultado como array de Telefonos
            return ltelefonos.toArray(new Telefono[0]);
        } catch (SQLException ex){
            Logger.printError(ex.getMessage());
        }
        return null;
    }
    public static boolean actualizarCliente(Cliente c){
        if (BDClientes.existeCliente(c.getDni())){
            java.sql.Connection db = new ConexionBD().getConnection();
            try {
                java.sql.PreparedStatement update = db.prepareStatement("UPDATE `gestionTienda`.`Clientes` SET nombre = ?, apellido1 = ?, apellido2 = ?, email = ? WHERE dni = ?");
                update.setString(1,c.getNombre());
                update.setString(2,c.getPrimerApellido());
                update.setString(3,c.getSegundoApellido());
                update.setString(4, c.getEmail());
                update.setString(5, c.getDni());
                if (update.executeUpdate() == 1){
                    return true;
                }
            }catch (SQLException ex){
                return false;
            }
        } else {//No existe
            return BDClientes.añadirCliente(c);
        }
        return false;
    }
    public static boolean actualizarTelefonos(Telefono[] telefonos, String dni){
        Telefono[] atelefonos = BDClientes.obtenerTelefonosCliente(dni);
        java.sql.Connection db = new ConexionBD().getConnection();
        try {
            java.sql.Statement delete = db.createStatement();
            int executeUpdate = delete.executeUpdate("DELETE  FROM `gestionTienda`.`Telefonos` WHERE dni = '" + dni + "'");
            
                añadirTelefonos(telefonos,dni);//Añadir telefonos nuevos
                return true;
            
        }catch (SQLException ex){
            añadirTelefonos(atelefonos, dni);
            return false;
        }
    }
    private static void añadirTelefonos(Telefono[] tel, String dni){
        for (Telefono temp : tel){
            BDClientes.añadirTelefono(temp, dni);
        }
    }
    public static boolean actualizarDireccion(Direccion d, String dni){
        
        if (BDClientes.existeDireccion(d)){
            Direccion antigua = BDClientes.obtenerDireccion(dni);
            java.sql.Connection db = new ConexionBD().getConnection();
            try {
                java.sql.Statement delete = db.createStatement();
                int executeUpdate = delete.executeUpdate("DELETE  FROM `gestionTienda`.`Direcciones` WHERE idDireccion = '" + dni + "'");
                if (executeUpdate == 1){
                    return BDClientes.añadirDireccion(d, dni);
                }
            }catch (SQLException ex){
                BDClientes.añadirDireccion(antigua, dni);
                return false;
            }
        }else {
            return BDClientes.añadirDireccion(d, dni);
        }
        return false;
    }
}
